﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
using Liang.Util.Task.Enums;

namespace Liang.Util.Task
{
	/// <summary>
	/// 时间策略配置
	/// </summary>
	public class TimerStrategyManager : IConfigurationSectionHandler
	{
		/// <summary>
		/// 请求服务配置
		/// </summary>
		public static TimerStrategyConfig StrategyConfig { get; set; }
		/// <summary>
		/// 静态构造函数
		/// </summary>
		static TimerStrategyManager()
		{
			ConfigurationManager.GetSection("TimerStrategyConfig");
		}
		/// <summary>
		/// 读取自定义配置节
		/// </summary>
		/// <param name="parent">父结点</param>
		/// <param name="configContext">配置上下文</param>
		/// <param name="section">配置区</param>
		/// <returns></returns>
		object IConfigurationSectionHandler.Create(object parent, object configContext, XmlNode section)
		{
			StrategyConfig = new TimerStrategyConfig();
			var config = new List<TimerStrategy>();

			foreach (XmlNode node in section.ChildNodes)
			{
				if (node.NodeType == XmlNodeType.Element)
				{
					switch (node.Name.ToLower())
					{
						case "default":
							StrategyConfig.Default = node.InnerText;
							break; ;
						case "timerstrategy":
							var tmp = new TimerStrategy();
							tmp.Dates = new List<DateTime>();
							tmp.Days = new List<int>();
							tmp.Months = new List<int>();
							SetTimerConfigValue(tmp, node);
							config.Add(tmp);
							break;
					}
				}
			}
			StrategyConfig.Config = config.ToArray();

			return StrategyConfig;
		}
		/// <summary>
		/// 设置定时器值
		/// </summary>
		/// <param name="Config"></param>
		/// <param name="node"></param>
		private void SetTimerConfigValue(TimerStrategy Config, XmlNode node)
		{
			int tmp;
			long longTmp;
			TimeSpan time;
			var times = new List<TimeSpan>();
			var dates = new List<DateTime>();

			foreach (XmlNode xn in node.ChildNodes)
			{
				if (xn.NodeType == XmlNodeType.Element)
				{
					switch (xn.Name.ToLower())
					{
						case "refname":
							Config.RefName = xn.InnerText;
							break;
						case "reentrant":
							Config.Reentrant = String.Compare(xn.InnerText, "true", true) == 0;
							break;
						case "timermode":
							if (xn.InnerText != null)
								Config.TimerMode = (TimerStrategyMode)Enum.Parse(typeof(TimerStrategyMode), xn.InnerText);
							break;
						case "delay":
							Int64.TryParse(xn.InnerText, out longTmp);
							Config.Delay = new TimeSpan(longTmp * 10000L);	// Delay配置值为毫秒
							break;
						case "interval":
							Int64.TryParse(xn.InnerText, out longTmp);		// Interval配置值为毫秒
							if (Config.StrategyByDay != null)
								Config.StrategyByDay.Interval = new TimeSpan(longTmp * 10000L);	// Delay配置值为毫秒								
							else
								Config.Interval = new TimeSpan(longTmp * 10000L);
							break;
						case "months":	// 指定哪几月份序号
							#region 获取月份列表
							if (!String.IsNullOrEmpty(xn.InnerText))
							{
								var list = new List<int>();
								var months = xn.InnerText.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
								for (var i = 0; i < months.Length; i++)
								{
									if (!Int32.TryParse(months[i], out tmp)) throw new Exception("Months配置不正确！");
									list.Add(tmp);
								}

								Config.Months = SortAndDistinct(list);
							}
							#endregion
							break;
						case "days":	// 指定哪几天的序号
							#region 获取天数列表
							if (!String.IsNullOrEmpty(xn.InnerText))
							{
								var list = new List<int>();
								var days = xn.InnerText.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
								for (var i = 0; i < days.Length; i++)
								{
									if (!Int32.TryParse(days[i], out tmp)) throw new Exception("Days配置不正确！");
									list.Add(tmp);
								}

								Config.Days = SortAndDistinct(list);
							}
							#endregion
							break;
						case "dates":
							SetTimerConfigValue(Config, xn);	// 设置时间策略
							break;
						case "date":
							var dt = DateTime.ParseExact("0004-" + xn.InnerText, "yyyy-M-d", null);
							dates.Add(dt);
							break;
						case "strategybyday":
							//还是用这个函数处理下一级的配置
							Config.StrategyByDay = new TimerStrategyByDay();
							SetTimerConfigValue(Config, xn);	// 设置时间策略
							break;
						case "begintime":
							if (String.IsNullOrEmpty(xn.InnerText)) xn.InnerText = "0:0:0";
							Config.StrategyByDay.BeginTime = TimeSpan.Parse(xn.InnerText);
							break;
						case "endtime":
							if (String.IsNullOrEmpty(xn.InnerText)) xn.InnerText = "0:0:0";
							Config.StrategyByDay.EndTime = TimeSpan.Parse(xn.InnerText);
							break;
						case "timepoints":
							SetTimerConfigValue(Config, xn);	// 设置时间策略
							break;
						case "timevalue":
							if (!TimeSpan.TryParse(xn.InnerText, out time))
								throw new Exception("时间配置不正确！");
							times.Add(time);
							break;
					}
				}
			}

			if (times.Count != 0)
				Config.StrategyByDay.TimePoints = times.ToArray();

			if (dates.Count != 0)
				Config.Dates = SortAndDistinct(dates);
		}

		/// <summary>
		/// 升排序和去重
		/// </summary>
		/// <param name="values"></param>
		/// <returns></returns>
		public static List<int> SortAndDistinct(List<int> values)
		{
			var list = new List<int>();
			values.Sort((x, y) => x - y);
			var tmp = -1;
			foreach (var intT in values)
			{
				if (tmp != intT)	// 目标是为了去重
				{
					list.Add(intT);
					tmp = intT;
				}
			}

			list.TrimExcess();
			return list;
		}

		/// <summary>
		/// 升排序和去重
		/// </summary>
		/// <param name="values"></param>
		/// <returns></returns>
		public static List<DateTime> SortAndDistinct(List<DateTime> values)
		{
			var list = new List<DateTime>();
			values.Sort((x, y) => x.DayOfYear - y.DayOfYear);
			var dt = DateTime.MaxValue;
			foreach (var intT in values)
			{
				if (dt != intT)	// 目标是为了去重
				{
					list.Add(intT);
					dt = intT;
				}
			}

			list.TrimExcess();
			return list;
		}
	}
}
